package cn.com.fattiger.framework.remoting.netty4.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

import java.util.concurrent.Executors;

import cn.com.fattiger.framework.remoting.netty4.common.protocol.handle.ReceivedHandle;
import cn.com.fattiger.framework.remoting.netty4.common.protocol.handle.SendHandle;
import cn.com.fattiger.framework.remoting.netty4.server.channel.ServerChannelInitializer;
import cn.com.fattiger.framework.remoting.netty4.server.handle.ServerReceivedHandle;
import cn.com.fattiger.framework.remoting.netty4.server.handle.ServerSendHandle;
import cn.com.fattiger.framework.remoting.server.AbstractServer;
import cn.com.fattiger.framework.remoting.server.Server;

public class NettyServer extends AbstractServer {

	// private static Logger log=LoggerFactory.getLogger(NettyServer.class);
	private int port = 8080;
	private EventLoopGroup bossGroup = null;
	private EventLoopGroup workerGroup = null;
	private ServerBootstrap b = null;
	private SendHandle sendHandle;
	private ReceivedHandle receivedHandle;
	private String hostName;

	public NettyServer(int port) {
		super();
		this.port = port;
		this.hostName = String.valueOf(port);
	}

	@Override
	public void start() throws Exception{
		sendHandle = new ServerSendHandle();
		receivedHandle = new ServerReceivedHandle(sendHandle,Executors.newFixedThreadPool(2 * Runtime.getRuntime().availableProcessors() + 1));
		bossGroup = new NioEventLoopGroup(1);
		workerGroup = new NioEventLoopGroup();
		try {
			b = new ServerBootstrap();
			b.group(bossGroup, workerGroup);
			b.channel(NioServerSocketChannel.class);
			
			b.option(ChannelOption.SO_KEEPALIVE, true);
			b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 60 * 1000);
			b.option(ChannelOption.SO_BACKLOG, 128);
			b.option(ChannelOption.SO_RCVBUF, 65535);
			b.option(ChannelOption.SO_SNDBUF, 65535);
			
			b.childOption(ChannelOption.TCP_NODELAY, true);
			b.childOption(ChannelOption.SO_REUSEADDR, true);
			b.childOption(ChannelOption.SO_RCVBUF, 65535);
			b.childOption(ChannelOption.SO_SNDBUF, 65535);
			
			b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
			
			b.handler(new LoggingHandler(LogLevel.INFO));
			b.childHandler(new ServerChannelInitializer(this, receivedHandle, hostName));
			b.bind(port).sync();
			// log.info("Start Server Port "+port);
		} catch (Exception e) {
			// log.error("Server Error", e);
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
			
			throw e;
		} finally {
			// stop();
		}
	}

	@Override
	public void stop() {
		// Map<String, List<ChannelManager>> maps =
		// GlobalServerChannelManager.getChannelManagerMap();
		// for (String key : maps.keySet()) {
		// try {
		// GlobalServerChannelManager.close(key);
		// } catch (Exception e) {
		// e.printStackTrace();
		// }
		// }
		// bossGroup.shutdownGracefully();
		// workerGroup.shutdownGracefully();
	}

	public static void main(String[] args) throws Exception{
		int port = 8081;
		Server server = new NettyServer(port);
		server.start();
		
		
		
		//启动的时候应该初始化处理器列表load and init.
		// Wokers.init();
		
		//serviceName --> processor
		//srv.flowbank.login --> net.netty.processor.LoginProcessor
	}

}
